package code.example.base.util.concurrent.container.blockinglist;


import code.example.tool.LogFactory;

/**
 *  由于synchronized 只有一个condition（waitset 只有一个队列），所以只能使有
 *  notifyAll(),而不能使用notify
 * @param <E>
 */
public class BlockingListBySync<E> implements BlockingList<E> {

    static final int MAXIMUM_CAPACITY = 1 << 30;
     int tableSizeFor(int cap) {
        int n = cap - 1;
        n |= n >>> 1;
        n |= n >>> 2;
        n |= n >>> 4;
        n |= n >>> 8;
        n |= n >>> 16;
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
    }
    Object items[]= null;
    volatile  int count = 0;
    int putIndex =0;
    int takeIndex = 0;
    public BlockingListBySync(int size){
        int realSize = tableSizeFor(size);
        items = new Object [realSize];
    }

    private void log(String message){
        LogFactory.getLog().info(Thread.currentThread().getName()+":"+message);
    }
    /**
     * 生产对象
     * @param e
     * @throws InterruptedException
     */
    @Override
    public   void put(E e) throws InterruptedException{
        synchronized (this){
            while(count ==items.length){
                    this.wait();
            }
            putIndex ++;
            putIndex = putIndex & (items.length-1);
            items[putIndex]= e;
            count++;



            this.notifyAll();
        }
    }

    public int size(){
        return count;
    }

    /**
     * 消费对象
     * @return
     * @throws InterruptedException
     */
    @Override
    public E take() throws InterruptedException{
        synchronized (this){
            while(count ==0){
                this.wait();
            }
            takeIndex ++;
            takeIndex = takeIndex & (items.length-1);
            count--;
            E e = (E)items[takeIndex];
            items[takeIndex] = null;
            this.notifyAll();
            return e;
        }
    }
}
